/*  
 * File name : tcp.c
 * Function  : tcp handle && driver control
 * Date      : 2024-04-25  
 * Version   : 0.1.0  
 */
/************************************************************************************
***************************************INCLUDE***************************************
*************************************************************************************/
#include "tcp.h"
#include "net.h"
#include "global.h"
#include "tool.h"
/************************************************************************************
***************************************EXTERN****************************************
*************************************************************************************/

/*
* func        : usage
* return      : error code
* input       : Command line arguments and sizes
* output      ：NULL
* author      date     modify
--------------------------------
 xintianyu  2024-4-10  create
*/
int usage(int argc, char *argv[])
{ 
    if (argc != 3)
    {  
        printf("Usage: %s <ip_address> <port>\n", argv[0]);  
        return ERROR;  
    }
    else
    {
        return NOERROR;
    }
}

/*
* func        : NULL function
* return      : NULL
* input       : NULL
* output      ：NULL
* author      date     modify
--------------------------------
 xintianyu  2024-4-10  create
*/
void do_nothing()
{
    /*void*/
}

/*
* func        : tcp handle
* return      : err code
* input       : Command line arguments and sizes
* output      ：NULL
* author      date     modify
--------------------------------
 xintianyu  2024-4-10  create
*/
int tcp_server(int argc, char *argv[]) 
{
    int server_fd, client_fd;  
    struct sockaddr_in server_addr, client_addr;  
    socklen_t client_len = sizeof(client_addr); 
    char *ip_address = argv[1];  
    int port = atoi(argv[2]);  
  
    /* 创建TCP套接字 */
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
        perror("socket creation failed");  
        exit(EXIT_FAILURE);  
    }  

    /* 支持快速重新绑定 */
	int b_reuse = 1;
	setsockopt (server_fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));

    /* 设置服务器地址信息 */ 
    memset(&server_addr, 0, sizeof(server_addr));  
    server_addr.sin_family = AF_INET;  
    server_addr.sin_addr.s_addr = inet_addr(ip_address);  
    server_addr.sin_port = htons(port);  
  
    /* 绑定套接字到服务器地址 */ 
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {  
        perror("bind failed");  
        exit(EXIT_FAILURE);  
    }  
  
    /* 监听套接字 */
    if (listen(server_fd, 5) < 0) {  
        perror("listen failed");  
        exit(EXIT_FAILURE);  
    }  
  
    printf("Server listening on %s:%d...\n", ip_address, port);  
	/* 处理僵尸进程 */
	signal(SIGCHLD, SIG_IGN);

    /* 接受客户端连接 */  
    if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) < 0) {  
        perror("accept failed");
        goto err1;
    }
    /* 打印客户端信息 */ 
    char client_ip[INET_ADDRSTRLEN];  
    inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);  
    printf("Client connected from %s:%d\n", client_ip, ntohs(client_addr.sin_port));
    if (ERROR == do_client(client_fd))
    {
        perror("client disconnect.....");
        goto err2;
    }

err2:
    close(client_fd);
err1:
    close(server_fd);
    return NOERROR;  
}

/************************************************************************************
***************************************LOCAL*****************************************
************************************************************************************/

/*
* func        : client handle
* return      : err code
* input       : file descriptor
* output      ：NULL
* author      date     modify
--------------------------------
 xintianyu  2024-4-10  create
 xintianyu  2024-4-25  V-0.1.0
*/
int do_client(int acceptfd)
{
    char rx_buffer[BUFFER_SIZE];
    int ret;
    
    while(1)
    {
        // 接收客户端消息
        memset(rx_buffer, 0, BUFFER_SIZE);
        ssize_t bytes_read = recv(acceptfd, rx_buffer, BUFFER_SIZE - 1, 0);  
        if (bytes_read < 0) 
        {  
            perror("recv failed");  
            return ERROR;
        }
        else
        {
            printf("Received message: %s\n", rx_buffer);
            if ('Q' == rx_buffer[0] || 0 == rx_buffer[0])
            {
                printf("client quit....\n");
                return ERROR;
            }
            else
            {
                ret = select_driver(rx_buffer, acceptfd);
            }
            if (ret != ERROR)
            {
                /*do nothing*/
            }
            else
            {
                // 回复客户端消息  
                //strcpy(tx_buffer, "Hello, client!\n");
                /*确保消息以换行符结尾，并打印接收到的消息*/  
                if (bytes_read > 0 && rx_buffer[bytes_read - 1] != '\n') {  
                    rx_buffer[bytes_read] = '\n';  
                    rx_buffer[bytes_read + 1] = '\0';  
                }
                if (send(acceptfd, rx_buffer, strlen(rx_buffer), 0) < 0) 
                {  
                    perror("send failed");  
                }
            }
        }
    }
	return NOERROR;
}

/*
* func        : driver handle
* return      : err code
* input       : <cmd> (device code) <accepted> (file descriptor)
* output      ：NULL
* author      date     modify
--------------------------------
 xintianyu  2024-4-10  create
 xintianyu  2024-4-25  V-0.1.0
*/
int select_driver(char * cmd, int acceptfd)
{
/* TODO 传递参数后需改为使用通信结构体 */
/* TODO 所有的魔鬼数字都要进行定义 */
    int ret = 0;
    int get_data = 0;
    MSG drv_msg;
    char *tx_buffer;
    char buf[32];
    char irda_data=' ';
    DIRECTION direction;
    CMD drv_cmd;

    if('@' == cmd[0])
    {
#if (STD_ON == DEBUG)
        //printf("cmd[0] = @\n");
#endif/*STD_ON == DEBUG*/
        drv_msg.device = extract_digit_number(cmd, 1, 3);
        //printf("device is %d\n", drv_msg.device);
        /*TODO 后续需升级为多线程模式调用驱动*/
        switch(drv_msg.device)
        {
            case 0:
                /*TODO 日志打印等级控制*/
                /*TODO用设备结构体后这里要封装一下*/
                printf("LED!!!\n");
                if ('g' == cmd[4])
                {
                    direction = direction_get;
                    drv_cmd = cmd_no;
                    led_handle(direction, &drv_cmd);
                    if (cmd_close == drv_cmd)
                    {
                        tx_buffer = "@000g0";
                    }
                    else if(cmd_open == drv_cmd)
                    {
                        tx_buffer = "@000g1";
                    }
                }
                else
                {
                    if ('1' == cmd[5])
                        drv_cmd = cmd_open;
                    else if ('0' == cmd[5])
                        drv_cmd = cmd_close;
                    direction = direction_put;
                    if (NOERROR == led_handle(direction, &drv_cmd))
                    {
                        tx_buffer = "@000p1";
                    }
                    else
                    {
                        tx_buffer = "@000p0";
                    }
                }               
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 1:
                printf("SR501!!!\n");
                /*TODO 这里封装成带回调函数的处理函数通过传入处理函数做数据处理*/
                if ('g' == cmd[4])
                {
                    
                    sr501_handle(&get_data);
                    if (sr501_some == get_data)
                    {
                        tx_buffer = "@001g1";
                    }
                    else if(sr501_nobody == get_data)
                    {
                        tx_buffer = "@001g0";
                    }
                }              
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 2:
                printf("SR04!!!\n");
                if ('g' == cmd[4])
                {
                    ret = sr04_handle(&get_data);
                    if (NOERROR == ret)
                    {
                        sprintf(buf,"@002g%03d", get_data);
                        tx_buffer = buf;
                    }
                    else
                    {
                        tx_buffer = "@002e";
                    }
                }
                printf(">>>>>>%s\n",tx_buffer);         
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 3:
                printf("IRDA!!!\n");
                if ('g' == cmd[4])
                {
                    ret = irda_handle(&irda_data);
                    if (NOERROR == ret)
                    {
                        sprintf(buf,"@003g%c", irda_data);
                        tx_buffer = buf;
                    }
                    else
                    {
                        tx_buffer = "@003e";
                    }
                }
                printf(">>>>>>%s\n",tx_buffer);         
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 4:
                printf("motor!!!\n");
                if ('s' == cmd[4])
                {
                    if(0 == cmd[5])
                    {
                        /*/0 /n*/
                        get_data = extract_digit_number(cmd, 6, (strlen(&cmd[5])-2));
                    }
                    else
                    {
                        get_data = -extract_digit_number(cmd, 6, (strlen(&cmd[5])-2));
                    }
                    printf("getdata == %d\n",get_data);
                    ret = motor_handle(get_data);
                    if (NOERROR == ret)
                    {
                        tx_buffer = "@004s";
                    }
                    else
                    {
                        tx_buffer = "@004e";
                    }
                }      
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 5:
                printf("dht11!!!\n");
                if ('g' == cmd[4])
                {
                    ret = dht11_handle(buf);
                    tx_buffer = buf;
                }
                printf(">>>>>>%s\n",tx_buffer);         
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 6:
                printf("ds18b20!!!\n");
                if ('g' == cmd[4])
                {
                    ret = ds18b20_handle(buf);
                    tx_buffer = buf;
                }
                printf(">>>>>>%s\n",tx_buffer);         
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 7:
                printf("AT24C02!!!\n");
                if ('g' == cmd[4])
                {
                    direction = direction_get;
                }
                else
                {
                    direction = direction_put;
                    printf("%s\n", &cmd[5]);
                    printf("写入长度  %d\n", strlen(&cmd[5]));
                    memset(buf, 0, 32);
                    strncpy(buf, &cmd[5], strlen(&cmd[5]));
                }

                ret = at24c02_handle(direction, buf, strlen(&cmd[5]));
                if (NOERROR == ret)
                {

                    tx_buffer = buf;
                }
                else
                {
                    tx_buffer = "@007e";
                }
                printf(">>>>>>%s\n",tx_buffer);
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            case 8:
                printf("DAC!!!\n");
                if ('p' == cmd[4])
                {
                    direction = direction_put;
                    get_data = extract_digit_number(cmd, 5, (strlen(&cmd[5])));
                    if (NOERROR == dac_handle(&get_data))
                    {
                        tx_buffer = "@008p";
                    }
                    else
                    {
                        tx_buffer = "@008e";
                    }

                }
                else
                {
                    tx_buffer = "@008e";
                }
                
                if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) < 0)
                {
                    perror("send failed");  
                }
                break;
            default:
                printf("Unknown equipment!!!\n");
        }
    }
    else
    {
        printf("cmd[0] ERROR!!!\n");
        ret = ERROR;
    }
    return ret;
}